//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_dataview_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/dataview_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/issue_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/requirement_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/notices/notices_dataview"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_dataview_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectDataViewApiImpl) CreateNode(ctx context.Context, req *project_dataview_api.CreateNodeRequest) (*project_dataview_api.CreateNodeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeId := uuid.NewString()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		nodeItem := &dataview_dao.NodeInfoDbItem{
			NodeId:   nodeId,
			ViewId:   req.ViewId,
			NodeType: uint32(req.NodeType),
			X:        req.X,
			Y:        req.Y,
			W:        req.W,
			H:        req.H,
			BgColor:  req.BgColor,
		}
		if req.NodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_GROUP {
			item, ok := req.NodeData.(*project_dataview_api.CreateNodeRequest_BaseGroupName)
			if ok {
				nodeItem.BaseGroupName = item.BaseGroupName
			}
		} else if req.NodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_TEXT {
			item, ok := req.NodeData.(*project_dataview_api.CreateNodeRequest_BaseText)
			if ok {
				nodeItem.BaseText = item.BaseText
			}
		} else if req.NodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_IFRAME {
			item, ok := req.NodeData.(*project_dataview_api.CreateNodeRequest_BaseIframeUrl)
			if ok {
				nodeItem.BaseIframeUrl = item.BaseIframeUrl
			}
		} else {
			item, ok := req.NodeData.(*project_dataview_api.CreateNodeRequest_RefTargetId)
			if ok {
				nodeItem.RefTargetId = item.RefTargetId
			}
		}

		err = dataview_dao.NodeDao.Insert(sessCtx, nodeItem)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.CreateNodeResponse{
			Code:   project_dataview_api.CreateNodeResponse_CODE_OK,
			NodeId: nodeId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.CreateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    nodeId,
	})
	return ret.(*project_dataview_api.CreateNodeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) UpdateNodePosition(ctx context.Context, req *project_dataview_api.UpdateNodePositionRequest) (*project_dataview_api.UpdateNodePositionResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.UpdateNodePositionResponse{
			Code:   project_dataview_api.UpdateNodePositionResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.NodeDao.UpdatePosition(sessCtx, req.ViewId, req.NodeId, req.X, req.Y)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.UpdateNodePositionResponse{
			Code: project_dataview_api.UpdateNodePositionResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.UpdateNodePositionResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) UpdateNodeSize(ctx context.Context, req *project_dataview_api.UpdateNodeSizeRequest) (*project_dataview_api.UpdateNodeSizeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code:   project_dataview_api.UpdateNodeSizeResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.NodeDao.UpdateSize(sessCtx, req.ViewId, req.NodeId, req.W, req.H)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.UpdateNodeSizeResponse{
			Code: project_dataview_api.UpdateNodeSizeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.UpdateNodeSizeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) UpdateNodeBgColor(ctx context.Context, req *project_dataview_api.UpdateNodeBgColorRequest) (*project_dataview_api.UpdateNodeBgColorResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code:   project_dataview_api.UpdateNodeBgColorResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.NodeDao.UpdateBgColor(sessCtx, req.ViewId, req.NodeId, req.BgColor)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.UpdateNodeBgColorResponse{
			Code: project_dataview_api.UpdateNodeBgColorResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.UpdateNodeBgColorResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) RemoveNode(ctx context.Context, req *project_dataview_api.RemoveNodeRequest) (*project_dataview_api.RemoveNodeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.RemoveNodeResponse{
			Code:   project_dataview_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist { //对象不存在
		return &project_dataview_api.RemoveNodeResponse{
			Code: project_dataview_api.RemoveNodeResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.NodeDao.Remove(sessCtx, req.ViewId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = dataview_dao.EdgeDao.RemoveByFromNode(sessCtx, req.ViewId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = dataview_dao.EdgeDao.RemoveByToNode(sessCtx, req.ViewId, req.NodeId)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.RemoveNodeResponse{
			Code: project_dataview_api.RemoveNodeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.RemoveNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.RemoveNodeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) ListNode(ctx context.Context, req *project_dataview_api.ListNodeRequest) (*project_dataview_api.ListNodeResponse, error) {
	emptyList := []*project_dataview_api.NodeInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.ListNodeResponse{
			Code:     project_dataview_api.ListNodeResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			NodeList: emptyList,
		}, nil
	}
	//检查权限
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.ListNodeResponse{
			Code:     project_dataview_api.ListNodeResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			NodeList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.ListNodeResponse{
			Code:     project_dataview_api.ListNodeResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			NodeList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.ListNodeResponse{
			Code:     project_dataview_api.ListNodeResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			NodeList: emptyList,
		}, nil
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.ListNodeResponse{
			Code:     project_dataview_api.ListNodeResponse_CODE_NO_VIEW,
			ErrMsg:   "数据视图不存在",
			NodeList: emptyList,
		}, nil
	}

	nodeItemList, err := dataview_dao.NodeDao.List(ctx, req.ViewId)
	if err != nil {
		return nil, err
	}
	nodeList := []*project_dataview_api.NodeInfo{}
	for _, nodeItem := range nodeItemList {
		nodeList = append(nodeList, nodeItem.ToNodeInfo())
	}

	return &project_dataview_api.ListNodeResponse{
		Code:     project_dataview_api.ListNodeResponse_CODE_OK,
		NodeList: nodeList,
	}, nil
}

func (apiImpl *ProjectDataViewApiImpl) GetNode(ctx context.Context, req *project_dataview_api.GetNodeRequest) (*project_dataview_api.GetNodeResponse, error) {
	emptyInfo := &project_dataview_api.NodeInfo{
		NodeData: &project_dataview_api.NodeInfo_RefTargetId{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Node:   emptyInfo,
		}, nil
	}
	//检查权限
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Node:   emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Node:   emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Node:   emptyInfo,
		}, nil
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
			Node:   emptyInfo,
		}, nil
	}

	nodeItem, err := dataview_dao.NodeDao.Get(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return &project_dataview_api.GetNodeResponse{
			Code:   project_dataview_api.GetNodeResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
			Node:   emptyInfo,
		}, nil
	}
	return &project_dataview_api.GetNodeResponse{
		Code: project_dataview_api.GetNodeResponse_CODE_OK,
		Node: nodeItem.ToNodeInfo(),
	}, nil
}

func (apiImpl *ProjectDataViewApiImpl) UpdateNodeData(ctx context.Context, req *project_dataview_api.UpdateNodeDataRequest) (*project_dataview_api.UpdateNodeDataResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := dataview_dao.NodeDao.Get(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}

	if !(nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_GROUP) || nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_TEXT) ||
		nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_IFRAME)) {
		return &project_dataview_api.UpdateNodeDataResponse{
			Code:   project_dataview_api.UpdateNodeDataResponse_CODE_NOT_ALLOW,
			ErrMsg: "不运行的操作",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		if nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_GROUP) {
			item, ok := req.NodeData.(*project_dataview_api.UpdateNodeDataRequest_BaseGroupName)
			if ok {
				err = dataview_dao.NodeDao.UpdateBaseGroupName(sessCtx, req.ViewId, req.NodeId, item.BaseGroupName)
				if err != nil {
					return nil, err
				}
			}
		} else if nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_TEXT) {
			item, ok := req.NodeData.(*project_dataview_api.UpdateNodeDataRequest_BaseText)
			if ok {
				err = dataview_dao.NodeDao.UpdateBaseText(sessCtx, req.ViewId, req.NodeId, item.BaseText)
				if err != nil {
					return nil, err
				}
			}
		} else if nodeItem.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_IFRAME) {
			item, ok := req.NodeData.(*project_dataview_api.UpdateNodeDataRequest_BaseIframeUrl)
			if ok {
				err = dataview_dao.NodeDao.UpdateBaseIframeUrl(sessCtx, req.ViewId, req.NodeId, item.BaseIframeUrl)
				if err != nil {
					return nil, err
				}
			}
		}
		return &project_dataview_api.UpdateNodeDataResponse{
			Code: project_dataview_api.UpdateNodeDataResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.UpdateNodeDataResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) ConvertToRefNode(ctx context.Context, req *project_dataview_api.ConvertToRefNodeRequest) (*project_dataview_api.ConvertToRefNodeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := dataview_dao.NodeDao.Get(ctx, req.ViewId, req.NodeId)
	if err != nil {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}
	if nodeItem.NodeType != uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_EMPTY_REF) {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NOT_ALLOW,
			ErrMsg: "视图节点不是空引用类型",
		}, nil
	}
	//检查目标类型和id
	if req.TargetNodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_REF_TASK || req.TargetNodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_REF_BUG {
		exist, err := issue_dao.IssueDao.Exist(ctx, req.ProjectId, req.RefTargetId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_dataview_api.ConvertToRefNodeResponse{
				Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_TARGET,
				ErrMsg: "引用目标不存在",
			}, nil
		}
	} else if req.TargetNodeType == project_dataview_api.NODE_TYPE_NODE_TYPE_REF_REQUIREMENT {
		exist, err := requirement_dao.RequirementInfoDao.Exist(ctx, req.ProjectId, req.RefTargetId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_dataview_api.ConvertToRefNodeResponse{
				Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NO_TARGET,
				ErrMsg: "引用目标不存在",
			}, nil
		}
	} else {
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code:   project_dataview_api.ConvertToRefNodeResponse_CODE_NOT_ALLOW,
			ErrMsg: "不能转换成目标类型",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.NodeDao.UpdateRefTarget(sessCtx, req.ViewId, req.NodeId, uint32(req.TargetNodeType), req.RefTargetId)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.ConvertToRefNodeResponse{
			Code: project_dataview_api.ConvertToRefNodeResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_dataview_api.ConvertToRefNodeResponse), nil
}
